/*
 * pps_bom
 */
package com.pitop.bom.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baidu.fsg.uid.UidGenerator;
import com.pitop.bom.dao.BomDAO;
import com.pitop.bom.dao.BomDetailDAO;
import com.pitop.bom.dao.BomDetailLogDAO;
import com.pitop.bom.dao.BomLogDAO;
import com.pitop.bom.entity.*;
import com.pitop.core.base.BaseDAO;
import com.pitop.core.base.BaseSVImpl;
import com.pitop.core.entity.Page;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.exceptions.BomException;
import com.pitop.core.tools.StringTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("bomSV")
@Slf4j
public class BomSVImpl extends BaseSVImpl<Bom, Long> implements BomSV {

    @Autowired
    private BomDAO bomDAO;

    @Autowired
    private BomLogDAO bomLogDAO;

    @Autowired
    private BomDetailDAO bomDetailDAO;

    @Autowired
    private BomDetailLogDAO bomDetailLogDAO;

    @Resource
    private UidGenerator uidGenerator;

    @Override
    protected BaseDAO getBaseDAO() {
        return bomDAO;
    }

    /**
     * 保存account对象
     * 1.参数合法性验证
     * 2.上级编码数据是否存在
     * 3.bom名称和代码是否存在
     * 4.添加bom日志
     *
     * @param entity 实体
     * @throws BaseException
     */
    @Override
    public void save(Bom entity) throws BaseException {
        entity.setCode(String.valueOf(uidGenerator.getUID()));
        entity.setState(BomState.Develop.name());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        super.save(entity);
    }


    /**
     * 加载一个对象Bom
     *
     * @param id
     * @param code 编码
     * @return Bom
     */
    @Override
    public Bom load(Long id, String code) {
        if (id == null && code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDAO.load(param);
    }

    /**
     * 加载一个对象Bom,(将查询关联数据)
     *
     * @param id
     * @param code 编码
     * @return Bom
     */
    @Override
    public Bom get(Long id, String code) {
        if (id == null && code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDAO.getDetail(id, code);
    }

    /**
     * 加载一个对象Bom 通过id
     *
     * @param id
     * @return Bom
     */
    @Override
    public Bom loadById(Long id) {
        if (id == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDAO.loadById(id);
    }

    /**
     * 加载一个对象Bom 通过code
     *
     * @param code 编码
     * @return Bom
     */
    @Override
    public Bom loadByCode(String code) {
        if (code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDAO.loadByCode(code);
    }

    @Override
    public Bom loadByName(String name) {
        if (name == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDAO.loadByName(name);
    }

    /**
     * 加载一个对象Bom 通过bomCode
     *
     * @param bomCode bom代码
     * @return Bom
     */
    @Override
    public Bom loadByBomCode(String bomCode) {
        if (bomCode == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> params = new HashedMap();
        params.put("bomCode", bomCode);
        return bomDAO.load(params);
    }

    /**
     * 加载一个对象Bom 通过id,(将查询关联数据)
     *
     * @param id
     * @return Bom
     */
    @Override
    public Bom getById(Long id) {
        if (id == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDAO.getById(id);
    }

    /**
     * 加载一个对象Bom 通过code,(将查询关联数据)
     *
     * @param code 编码
     * @return Bom
     */
    @Override
    public Bom getByCode(String code) {
        if (code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Bom bom =  bomDAO.getByCode(code);
        if(bom != null && StringTools.isNotEmpty(bom.getPreCode())) {
            Bom preBom = bomDAO.getByCode(bom.getPreCode());
            if(preBom != null) {
                bom.setPreName(preBom.getName());
            }
        }
        return bom;
    }

    /**
     * 根据主键id,oldStates 共同更新 Bom 的状态到newState状态
     *
     * @param id
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateById(Long id, BomState newState, BomState... oldStates) {
        if (id == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        bomDAO.updateStateById(id, new Date(), newState.name(), states);
    }

    /**
     * 根据主键code,oldStates 共同更新 Bom 的状态到newState状态
     *
     * @param code      编码
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateByCode(String code, BomState newState, BomState... oldStates) {
        if (code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        bomDAO.updateStateByCode(code, new Date(), newState.name(), states);
    }

    /**
     * 根据主键id 更新 Bom 的状态到另一个状态
     *
     * @param id
     * @param state 状态
     */
    @Override
    public void updateById(Long id, BomState state) {
        if (id == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        bomDAO.updateById(id, state.name(), new Date());
    }

    /**
     * 根据主键code 更新 Bom 的状态到另一个状态
     *
     * @param code  编码
     * @param state 状态
     */
    @Override
    public void updateByCode(String code, BomState state) {
        if (code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        bomDAO.updateByCode(code, state.name(), new Date());
    }


    /**
     * 删除对象Bom
     *
     * @param id * @param code 编码
     * @return Bom
     */
    @Override
    public void delete(Long id, String code) {
        if (id == null && code == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        bomDAO.delete(param);
    }


    /**
     * 查询Bom分页
     *
     * @param bom    对象
     * @param offset 查询开始行
     * @param limit  查询行数
     * @return List<Bom>
     */
    @Override
    public List<Bom> list(Bom bom, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }

        Map<String, Object> map = null;
        if (bom != null) {
            map = JSON.parseObject(JSON.toJSONString(bom, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        List<Bom> bomList = bomDAO.list(map, new RowBounds(offset, limit));
        if(bomList.size() > 0 ) {
            for (Bom bomFlag : bomList) {
                if(StringTools.isNotEmpty(bomFlag.getPreCode())) {
                    bomFlag.setPreName(bomDAO.loadByCode(bomFlag.getPreCode()).getName());
                }
            }
        }
        return  bomList;
    }

    @Override
    public int count(Bom bom) {
        Map<String, Object> map = null;
        if (bom != null) {
            map = JSON.parseObject(JSON.toJSONString(bom, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return bomDAO.count(map);
    }

    /**
     * 查询Bom分页
     *
     * @param id     * @param code  编码
     * @param offset 查询开始行
     * @param limit  查询行数
     * @return List<Bom>
     */
    @Override
    public List<Bom> list(Long id, String code, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDAO.list(param, new RowBounds(offset, limit));
    }

    @Override
    public int count(Long id, String code) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDAO.count(param);
    }

    /**
     * 添加bom信息
     *
     * @param entity  bom信息
     * @param account 账户信息
     * @param code    账户编码
     */
    @Override
    public void save(Bom entity, String account, String code) {
        //1.参数合法性验证
        if (entity == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Empty_Param);
        }
        if (StringTools.isEmpty(entity.getName()) || StringTools.isEmpty(entity.getBomCode())) {
            throw new BomException(BaseException.BaseExceptionEnum.Empty_Param);
        }
        //2.上级编码是否存在
        Bom fatherBom = null;
        if (StringTools.isNotEmpty(entity.getPreCode())) {
            fatherBom = bomDAO.loadByCode(entity.getPreCode());
        }
        //设置bom等级
        if (fatherBom == null) {
            entity.setLevel(1);
        } else {
            entity.setLevel(fatherBom.getLevel() + 1);
        }
        entity.setCode(String.valueOf(uidGenerator.getUID()));
        entity.setState(BomState.Develop.name());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        super.save(entity);

        //4.添加bom日志
        String summary = "管理员" + account + "创建了bom:" + entity.getName();
        BomLog bomLog = new BomLog();
        bomLog.setBomCode(entity.getCode());
        bomLog.setEvent(BomLogState.Create.name());
        bomLog.setOperateCode(code);
        bomLog.setOperateName(account);
        bomLog.setSummary(summary);
        bomLog.setCreateTime(new Date());
        bomLogDAO.insert(bomLog);
    }

    /**
     * 修改bom信息
     *
     * @param bom     bom信息
     * @param account 账户信息
     * @param code    账户编码
     */
    @Override
    public void modify(Bom bom, String account, String code) {
        //1.参数合法性验证
        if (bom == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Empty_Param);
        }
        if (StringTools.isEmpty(bom.getName()) || StringTools.isEmpty(bom.getBomCode())) {
            throw new BomException(BaseException.BaseExceptionEnum.Empty_Param);
        }

        //2.上级编码是否存在
        Bom fatherBom = null;
        if (StringTools.isNotEmpty(bom.getPreCode())) {
            fatherBom = bomDAO.loadByCode(bom.getPreCode());
        }
        //3.设置bom等级
        if (fatherBom == null) {
            bom.setLevel(1);
        } else {
            bom.setLevel(fatherBom.getLevel() + 1);
        }
        bom.setUpdateTime(new Date());
        super.modify(bom);

        //4.添加bom日志
        String summary = "管理员" + account + "修改了bom:" + bom.getName();
        BomLog bomLog = new BomLog();
        bomLog.setBomCode(bom.getCode());
        bomLog.setEvent(BomLogState.Modify.name());
        bomLog.setOperateCode(code);
        bomLog.setOperateName(account);
        bomLog.setSummary(summary);
        bomLog.setCreateTime(new Date());
        bomLogDAO.insert(bomLog);
    }

    /**
     * 修改状态
     *
     * @param code  组件编码
     * @param state 状态
     */
    @Override
    public void updateState(String code, String state) {
        Bom bom = bomDAO.loadByCode(code);
        if (bom == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        bom.setState(state);
        bomDAO.update(bom);
    }

    /**
     * 复制
     * 1.复制bom，修改id，编码，状态和时间
     * 2.复制bom日志
     * 3.复制bom明细：修改id，编码，状态
     * 4.复制bom明细日志
     *
     * @param code        bom编码
     * @param account     管理员
     * @param accountCode 管理员编码
     */
    @Override
    public void copy(String code, String account, String accountCode) {
        Bom bom = bomDAO.getByCode(code);
        if (bom == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        //1.复制bom，修改id，编码，状态和时间
        Bom copyBom = bom;
        copyBom.setId(null);
        copyBom.setCode(String.valueOf(uidGenerator.getUID()));
        copyBom.setName(bom.getName() + "_copy");
        if (StringTools.isNotEmpty(bom.getBomCode())) {
            copyBom.setBomCode(bom.getBomCode() + "_copy");
        }
        copyBom.setState(BomState.Develop.name());
        copyBom.setCreateTime(new Date());
        copyBom.setUpdateTime(new Date());
        bomDAO.insert(bom);

        //2.复制bom日志
        String summery = "管理员" + account + "复制了bom" + bom.getName();
        BomLog bomLog = new BomLog(copyBom.getCode(), BomLogState.Copy.name(), accountCode, account, summery);
        bomLogDAO.insert(bomLog);

        //3.复制bom明细：修改id，编码，状态
        List<BomDetail> bomDetails = bom.getBomDetailList();
        if (bomDetails.size() > 0) {
            for (BomDetail bomDetail : bomDetails) {
                bomDetail.setId(null);
                bomDetail.setCode(String.valueOf(uidGenerator.getUID()));
                bomDetail.setBomCode(copyBom.getCode());
                bomDetail.setState(BomDetailState.Develop.name());
                bomDetailDAO.insert(bomDetail);

                //4.保存日志信息
                summery = "管理员" + account + "复制了bom:" + bom.getName() + ",bom明细是" + bomDetail.getName();
                BomDetailLog bomDetailLog = new BomDetailLog(bomDetail.getCode(), BomDetailLogState.Copy.name(), accountCode, account, summery);
                bomDetailLogDAO.insert(bomDetailLog);
            }
        }

    }

    /**
     * 查询未绑定此成品的bom
     *
     * @param productCode 成品编码
     * @param name
     * @param bomCode
     * @param offset      当前页
     * @param limit       分页大小   @return
     */
    @Override
    public List<Bom> queryUnBindProductBomList(String productCode, String name, String bomCode, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("productCode", productCode);
        params.put("state", BomState.Stable.name());
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.queryUnBindProductBomList(params, new RowBounds(offset, limit));
    }

    @Override
    public Integer countUnBindProductBomList(String productCode, String name, String bomCode) {
        Map<String, Object> params = new HashMap<>();
        params.put("productCode", productCode);
        params.put("state", BomState.Stable.name());
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.countUnBindProductBomList(params);
    }

    /**
     * 查询已绑定此成品的bom
     *
     * @param productCode 成品编码
     * @param name
     * @param bomCode     @return
     * @param offset      当前页
     * @param limit       分页大小
     */
    @Override
    public List<Bom> queryBindProductBomList(String productCode, String name, String bomCode, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("productCode", productCode);
        params.put("name", name);
        params.put("state", BomState.Stable.name());
        params.put("bomCode", bomCode);
        return bomDAO.queryBindProductBomList(params, new RowBounds(offset, limit));
    }

    @Override
    public Integer countBindProductBomList(String projectCode, String name, String bomCode) {
        Map<String, Object> params = new HashMap<>();
        params.put("projectCode", projectCode);
        params.put("state", BomState.Stable.name());
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.countBindProductBomList(params);
    }

    /**
     * 查询未绑定项目的bom
     *
     * @param projectCode 项目编码
     * @param name        bom名称
     * @param bomCode     bom编码
     * @param offset      当前页
     * @param limit       分页大小
     * @return
     */
    @Override
    public List<Bom> queryUnBindProjectBomList(String projectCode, String name, String bomCode, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }
        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("projectCode", projectCode);
        params.put("state", BomState.Stable.name());
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.queryUnBindProjectBomList(params, new RowBounds(offset, limit));
    }

    @Override
    public Integer countUnBindProjectBomList(String projectCode, String name, String bomCode) {
        Map<String, Object> params = new HashMap<>();
        params.put("projectCode", projectCode);
        params.put("state", BomState.Stable.name());
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.countUnBindProjectBomList(params);
    }

    /**
     * 查询已绑定项目的bom
     *
     * @param projectCode 项目编码
     * @param name        bom名称
     * @param bomCode     bom编码
     * @param offset      当前页
     * @param limit       分页大小
     * @return
     */
    @Override
    public List<Bom> queryBindProjectBomList(String projectCode, String name, String bomCode, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("projectCode", projectCode);
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.queryBindProjectBomList(params, new RowBounds(offset, limit));
    }

    @Override
    public Integer countBindProjectBomList(String projectCode, String name, String bomCode) {
        Map<String, Object> params = new HashMap<>();
        params.put("projectCode", projectCode);
        params.put("name", name);
        params.put("bomCode", bomCode);
        return bomDAO.countBindProjectBomList(params);
    }
}
